<template>
  <div style="height: 250px;width: 100%;">
    <div  ref="echartMemoryRef" style="height: 100%;width: 300px;float: left"></div>
    <div  ref="echartCpuRef" style="height: 100%;width: 300px;float: left"></div>
    <div  ref="echartStorageRef" style="height: 100%;width: 300px;float: left"></div>
    <div  ref="echartLineRef" style="height: 100%;width: calc(100% - 900px);float: left"></div>
    <div style="clear: both"></div>
  </div>
  <div >
    <div>Docker进程</div>
    <div style="width: 100%;height: 250px;">
      <Table :show-page="true" ref="tableRef" :show-line-number="true"
             :showCheckBox="false"  :columns="columns"  >
      </Table>
    </div>
    <div style="margin-top: 5px">
      <el-form ref="searchRef" :model="searchFormData">
        <el-row :gutter="10">
          <el-col :span="4">
            <el-form-item label="容器名称">
              <el-input type="text" v-model="searchFormData.containerName"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="容器ID">
              <el-input type="text" v-model="searchFormData.containerID"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-button @click="searchClick">查询</el-button>
            <el-button @click="resetSearchClick">重置</el-button>
          </el-col>
        </el-row>
      </el-form>
    </div>
    <div style="width: 100%;height: 250px;">
      <Table :show-page="true" ref="containerTableRef" :show-line-number="true"
             :showCheckBox="false" :url="tableUrl" :columns="containerColumns"  >
        <template v-slot:handle="slotProps">
          <el-button  @click.stop="showRunningLog(slotProps.rowData,slotProps.rowIndex)">日志</el-button>
          <el-button  @click.stop="saveRunningLog(slotProps.rowData,slotProps.rowIndex)">转存日志</el-button>
          <el-button @click.stop="showResourceLog(slotProps.rowData,slotProps.rowIndex)">资源</el-button>
          <el-button @click.stop="showTopInfo(slotProps.rowData,slotProps.rowIndex)">Top信息</el-button>
          <el-button @click.stop="showTopInfo(slotProps.rowData,slotProps.rowIndex)">裁决日志</el-button>
        </template>
      </Table>
    </div>
  </div>

  <el-dialog title="运行日志" v-model="runningDialogVisible" width="1000" :close-on-click-modal="false">
    <div ref="logsRef" style="width: 100%;height: 500px;overflow-y: auto" v-html="runningLogIno"></div>
  </el-dialog>

  <el-dialog title="容器Top信息" v-model="topDialogVisible" width="1000" :close-on-click-modal="false">
    <table class="docker-container-top-table">
        <thead>
          <th>UID</th>
          <th>PID</th>
          <th>PPID</th>
          <th>C</th>
          <th>STIME</th>
          <th>TTY</th>
          <th>TIME</th>
          <th>CMD</th>
        </thead>
      <tbody>
        <tr v-for="(item, index ) in dockerContainerTopInfo">
          <td>{{item.uid}}</td>
          <td>{{item.pid}}</td>
          <td>{{item.ppid}}</td>
          <td>{{item.c}}</td>
          <td>{{item.stime}}</td>
          <td>{{item.tty}}</td>
          <td>{{item.time}}</td>
          <td>{{item.cmd}}</td>
        </tr>
      </tbody>
    </table>
  </el-dialog>

  <el-dialog title="资源" v-model="resourceDialogVisible" width="1000" :close-on-click-modal="false">
    <el-form :model="resourceInfo" style="width: 645px;margin-top: 20px;text-align: left" :label-width="150" >
      <el-row>
        <el-col :span="8">
          <el-form-item label="cpu%">
            <el-text>{{resourceInfo.useCpuPercent}}</el-text>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="内存">
            <el-text>{{resourceInfo.useMemory}}</el-text>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="内存限制">
            <el-text>{{resourceInfo.limitMemory}}</el-text>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="8">
          <el-form-item label="内存%">
            <el-text>{{resourceInfo.useMemoryPercent}}</el-text>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="网络入">
            <el-text>{{resourceInfo.useNetworkIn}}</el-text>
          </el-form-item>
        </el-col>
        <el-col :span="8">
          <el-form-item label="网络出">
            <el-text>{{resourceInfo.useNetworkOut}}</el-text>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="11">
          <el-form-item label="PID">
            <el-text>{{resourceInfo.pid}}</el-text>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </el-dialog>

</template>
<script setup>

import Table from "@/components/plugs/table/Table.vue";
import {inject, onMounted, onUnmounted, reactive, ref, toRaw} from "vue";
import {AXIOS_NAME} from "@/constant/constant.js";
import * as echarts  from 'echarts'
import {ElMessage, ElMessageBox} from "element-plus";

const echartMemoryRef = ref(null);
const echartCpuRef = ref(null);
const echartStorageRef = ref(null);
const echartLineRef = ref(null);

let memoryChart = null;
let cpuChart = null;
let storageChart = null;
let lineChart = null;

const $axios = inject(AXIOS_NAME);
const resourceRowContainerId = ref(null);
const runningRowContainerId = ref(null);

const searchFormData = reactive({
  containerName: "",
  containerID: ""
});
const dockerContainerTopInfo = reactive([]);
const logsRef = ref(null);
const resourceInfo = reactive({});
const runningLogIno = ref("");
const topDialogVisible = ref(false);
const runningDialogVisible = ref(false);
const resourceDialogVisible = ref(false);
const containerTableRef = ref(null);
const tableRef = ref(null);
const tableUrl = ref("/deploy/getRealContainerInfo?deployState=1");
let interval;


const getDockerContainersState = () => {
  $axios.post('/deploy/getContainersStat').then(response => {
    const data = response.data;
    tableRef.value.setData(data.data);
  });
}

const containerColumns = [
  {field: "imageName", "desc": "镜像名称", colFormatVal: function (rowData, dicData, colIndex, rowIndex) {
      return rowData.imageName + ":" + rowData.imageTag;
    }
  },
  {field: "containerName", "desc": "容器名称"},
  {field: "containerID", "desc": "容器ID"},
  {field: "containerType", "desc": "容器类型", dicType: "container_type"},
  {field: "networkIp", "desc": "网络"},
  {field: "deployState", "desc": "部署状态", dicType: "deploy_state"},
  {field: "runState", "desc": "运行状态", dicType: "run_state"},
  {field: "ports", "desc": "端口"},
  {field: "handle", "desc": "操作", isSlot: true, width: 450}
];
const columns = [
  {field: "containerName", "desc": "容器名称"},
  {field: "useCpuPercent", "desc": "cpu%"},
  {field: "useMemory", "desc": "内存"},
  {field: "limitMemory", "desc": "内存限制"},
  {field: "useMemoryPercent", "desc": "内存%"},
  {field: "useNetworkIn", "desc": "网络输入"},
  {field: "useNetworkOut", "desc": "网络输入"},
  {field: "blockIn", "desc": "块输入"},
  {field: "blockOut", "desc": "块输入"},
  {field: "pid", "desc": "pid"},
  {field: "showTime", "desc": "时间",width:"250"}
];

const searchClick = () => {
  containerTableRef.value.reload(toRaw(searchFormData));
}

const resetSearchClick = () => {
  searchFormData.containerName = '';
  searchFormData.containerID = '';
}

const showRunningLog = (rowData,rowIndex) =>{
  runningLogIno.value = "";
  runningDialogVisible.value = true;
  runningRowContainerId.value = rowData.containerID;
  getDockerLogsInfo();
}

const saveRunningLog = (rowData,rowIndex) =>{
  ElMessageBox.confirm(
      '是否转存日志?','提示',{
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }
  ).then(() => {
    $axios.post("/monitor/saveContainerLogs",{"containerId":rowData.containerID}).then(response => {
      const data = response.data;
      ElMessage.info(data.msg);
    });
  });

}

const showTopInfo = (rowData,rowIndex) =>{
  topDialogVisible.value = true;
  $axios.post("/monitor/getDockerContainerTop",{"containerId":rowData.containerID}).then(response => {
    const data = response.data;
    dockerContainerTopInfo.clear();
    if(data.code == 1){
      dockerContainerTopInfo.pushAll(data.data);
    }
  });
}

const showResourceLog = (rowData,rowIndex) =>{
  resourceDialogVisible.value = true;
  resourceRowContainerId.value = rowData.containerID;
  getDockerResourceInfo();
}

const scrollToBottom = () => {
  let scrollElem = contRef.value;
  scrollElem.scrollTo({ top: scrollElem.scrollHeight, behavior: "smooth" });
};
let intervalGetData;

onUnmounted(() => {
  if(intervalGetData != undefined){
    clearInterval(intervalGetData);
  }
});
intervalGetData = setInterval(function (){
  getDockerContainersState();
  getDockerResourceInfo();
  getDockerLogsInfo();
  getEchartData();
},2000);

function getDockerResourceInfo(){
  if(!resourceDialogVisible.value){
    return;
  }
  $axios.post("/monitor/getResourceInfoByContainerId",{"containerId":resourceRowContainerId.value}).then(response => {
    const data = response.data.data;
    for(const key in data){
      resourceInfo[key] = data[key];
    }
  });
}

function getDockerLogsInfo(){
  if(!runningDialogVisible.value){
    return;
  }
  $axios.post("/monitor/getMonitorInfoByContainerId",{"containerId":runningRowContainerId.value}).then(response => {
    const data = response.data.msg;
    if(data == null || data == undefined ||data == 'null'){
      return;
    }
    if( response.data.code != 1){
      return;
    }
    runningLogIno.value += data;
    scrollToBottom();
  });
}
onMounted(() =>{
  memoryChart = echarts.init(echartMemoryRef.value);
  cpuChart = echarts.init(echartCpuRef.value);
  storageChart = echarts.init(echartStorageRef.value);
  lineChart = echarts.init(echartLineRef.value);
  getEchartData();
});
const getEchartData = () =>{
  $axios.post("/monitor/getLinuxBaseInfo",{}).then(response => {
    const data = response.data;
    console.log(data);
    if(data.code != 1 || data.data.length <= 0){
      return;
    }
    const lastData = data.data[0];
    handlPieEchart('内存\n'+lastData.memoryTotal+"G",lastData,lastData.memoryTotal,lastData.usedMemory,
        '占用' + lastData.usedMemory + "G",lastData.freeMemory,"剩余" + lastData.freeMemory + "G" ,memoryChart);
    handlPieEchart('CPU\n' + lastData.cpuGHZ  +"GHZ",lastData,100,lastData.usedCpuPercent,
        '占用' + lastData.usedCpuPercent + "%",lastData.freeCpuPercent,"剩余" + lastData.freeCpuPercent + "%" ,cpuChart);
    handlPieEchart('存储\n' + lastData.totalStorage + "G",lastData,lastData.totalStorage,lastData.usedStorage,
        '占用' + lastData.usedStorage + "G",lastData.freeStorage,"剩余" + lastData.freeStorage + "G" ,storageChart);
    handleLineEchart(data.data);
  });
}


const handlPieEchart = (name,data,total,used,usedName,remain,remainName,myChart) =>{
  let option = {
    tooltip: {
      trigger: 'item'
    },
    legend: {
      top: '5%',
      left: 'center'
    },
    graphic: [
      {
        //环形图中间添加文字
        type: "text", //通过不同top值可以设置上下显示
        left: "center",
        top: "center",
        style: {
          text: name,
          textAlign: "center",
          fill: "black", //文字的颜色
          fontSize: 18,
          lineHeight: 20,
        },
      },
    ],
    series: [
      {
        name: 'Access From',
        type: 'pie',
        radius: ['40%', '70%'],
        avoidLabelOverlap: false,
        label: {
          show: false,
          position: 'center'
        },
        emphasis: {
          label: {
            show: true,
            fontSize: 40,
            fontWeight: 'bold'
          }
        },
        labelLine: {
          show: false
        },
        data: [
          { value: used, name: usedName },
          { value:remain, name: remainName },
        ]
      }
    ]
  }
  myChart.setOption(option);
}

const handleLineEchart = (data) =>{
  let xAxis = [];
  let revData = [];
  let senData = [];
  data.forEach( (item,index) => {
    xAxis.push((index + 1) + "s");
    revData.push(item.networkIn);
    senData.push(item.networkOut);
  });
  let options  = {
    title: {
      text: '吞吐'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['接收', '发送']
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
    },
    toolbox: {
      feature: {
        saveAsImage: {}
      }
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: xAxis
    },
    yAxis: {
      type: 'value',
      axisLabel: { //刻度标签的内容格式器，支持字符串模板和回调函数两种形式。
        formatter: '{value} kB/s'
      }
    },
    series: [
      {
        name: '接收',
        type: 'line',
        stack: 'Total',
        data: revData
      },
      {
        name: '发送',
        type: 'line',
        stack: 'Total',
        data: senData
      },
    ]
  };
  lineChart.setOption(options);
}

</script>

<style scoped>
.docker-container-top-table{
  width: 100%;
  text-align: left;
  border: 0px;
  border-collapse: collapse;
}
.docker-container-top-table tr,thead{
  height: 35px;
  border-bottom: 1px solid #F0F0F0;
}
</style>